
#ifndef SX_FIXED_TIMELINE_CONTROLLER_H
#define SX_FIXED_TIMELINE_CONTROLLER_H

#include <sxPlotController.h>
#include <sxFixedTimeline.h>
#include <sxCuboid_Archetype.h>

namespace Sx { namespace Interface { class Viewport; } }
namespace Sx { namespace Interface { class Canvas; } }

using Sx::Interface::PlotController;
using Sx::Graphics::Archetypes::Objects::Cuboid_Archetype;
using Sx::Interface::ScenePickingController;
using Sx::Interface::Viewport;
using Sx::Interface::Canvas;
using Sx::Interface::MouseButton;
using Sx::Interface::ModifierKey;

namespace Sx {
namespace Multimedia {

class Replayable;

namespace Interface {

class FixedTimelineController : public PlotController, public FixedTimeline {
public:
	FixedTimelineController(Viewport* viewport, 
		const std::shared_ptr<Canvas>& canvas, 
		const std::shared_ptr<ScenePickingController>& pickingController, 
		const std::shared_ptr<RendererImplementation>& cameraRenderer, 
		const std::shared_ptr<RendererImplementation>& plotRenderer,
		const std::shared_ptr<RendererImplementation>& cuboidRenderer);

	FixedTimelineController(Viewport* viewport,
		const std::shared_ptr<Canvas>& canvas, 
		const std::shared_ptr<ScenePickingController>& pickingController, 
		const std::shared_ptr<RendererImplementation>& cameraRenderer, 
		const std::shared_ptr<RendererImplementation>& plotRenderer,
		const std::shared_ptr<RendererImplementation>& cuboidRenderer,
		unsigned int nxTicks,
		unsigned int pxTicks,
		unsigned int nyTicks,
		unsigned int pyTicks,
		unsigned int nzTicks,
		unsigned int pzTicks,
		float spacing);

	virtual ~FixedTimelineController();

	/* Viewport Interface Overriding */
	virtual bool initialize();
	virtual void render() const;

	/* Replayable */
	void setReplayable(const std::shared_ptr<Replayable>& replayable);

	/* Viewport Controller Mouse Events */
	virtual void mousePressEvent(int x, int y, MouseButton button, ModifierKey modifierKey);
	virtual void mouseReleaseEvent(int x, int y, MouseButton button, ModifierKey modifierKey);
	virtual void mouseClickEvent(int x, int y, MouseButton button, ModifierKey modifierKey);
	virtual void mouseMoveEvent(int x, int y, MouseButton button, ModifierKey modifierKey);
	virtual void mouseWheelEvent(int delta);
	virtual bool mouseMoveSlider(int x, int y, MouseButton button, ModifierKey modifierKey);

	/* Fixed-Timeline interface implementation */
	bool setCurrentTime(unsigned int time);
	bool incrementTime();
	bool decrementTime();
	bool setCurrentFrame(unsigned int frame);
	bool setEndTime(unsigned int endTime);
	bool setFrameCount(unsigned int frameCount);

	unsigned int getCurrentTime() const;
	unsigned int getStartTime() const;
	unsigned int getEndTime() const;

	/* Returns the number of frames represented by this time-line. */
	unsigned int size() const;

	bool setDivisions(unsigned int count);
	bool setSliderScale(float scale);

protected:
	std::shared_ptr<Replayable> replayable;
	std::shared_ptr<Cuboid_Archetype> slider;

	unsigned int startTime, endTime, currentTime;

	/* Slider Movement and Snapping */
	float sliderScale;
	bool draggingSlider;
	bool gridSnap;
	float snapSpacing;

	/*
	 * The actual movement amount accumulated by the mouse dragging the slider
	 * across the time-line. This is used in coordination with grid-snap.
	 */
	float currentSliderPosition;

	/* 
	 * Every unit length section of the time-line is divided into this number of
	 * equal intervals.
	 */
	unsigned int divisions;
};

}

}

}

#endif
